/*!
 * \file test_his_data_replayer.cpp
 * \project	WonderTrader
 *
 * \author Wesley
 * \date 2025/01/01
 * 
 * \brief HisDataReplayer历史数据回放器的单元测试
 * 
 * \details 测试HisDataReplayer的核心功能：
 *          - 历史数据加载和管理
 *          - Tick数据回放
 *          - K线数据回放
 *          - Level2数据回放（委托队列、委托明细、成交明细）
 *          - 复权因子处理
 *          - 时间控制和调度
 *          - 数据接收器集成
 */
#include <gtest/gtest.h>
#include <gmock/gmock.h>
#include "../../src/WtBtCore/HisDataReplayer.h"
#include "../../src/WtBtCore/HisDataMgr.h"
#include "../../src/Share/IniHelper.hpp"
#include "../../src/Includes/WTSVariant.hpp"
#include "../../src/Includes/WTSDataDef.hpp"
#include "../../src/Includes/WTSSessionInfo.hpp"
#include "../../src/Includes/WTSContractInfo.hpp"

using ::testing::_;
using ::testing::Return;
using ::testing::NiceMock;
using ::testing::AtLeast;
using ::testing::Invoke;

/*!
 * \class MockDataSink
 * \brief 模拟数据接收器
 * 
 * \details 用于测试回放器向外部推送数据的功能
 */
class MockDataSink : public IDataSink {
public:
    MOCK_METHOD(void, handle_tick, (const char* stdCode, WTSTickData* curTick), (override));
    MOCK_METHOD(void, handle_order_queue, (const char* stdCode, WTSOrdQueData* curOrdQue), (override));
    MOCK_METHOD(void, handle_order_detail, (const char* stdCode, WTSOrdDtlData* curOrdDtl), (override));
    MOCK_METHOD(void, handle_transaction, (const char* stdCode, WTSTransData* curTrans), (override));
    MOCK_METHOD(void, handle_bar_close, (const char* stdCode, const char* period, uint32_t times, WTSBarStruct* newBar), (override));
    MOCK_METHOD(void, handle_schedule, (uint32_t uDate, uint32_t uTime), (override));
    MOCK_METHOD(void, handle_init, (), (override));
    MOCK_METHOD(void, handle_session_begin, (uint32_t uCurDate), (override));
    MOCK_METHOD(void, handle_session_end, (uint32_t uCurDate), (override));
    MOCK_METHOD(void, handle_replay_done, (), (override));
    MOCK_METHOD(void, on_tick_updated, (const char* stdCode, WTSTickData* newTick), (override));
    MOCK_METHOD(void, on_ordque_updated, (const char* stdCode, WTSOrdQueData* newOrdQue), (override));
    MOCK_METHOD(void, on_orddtl_updated, (const char* stdCode, WTSOrdDtlData* newOrdDtl), (override));
    MOCK_METHOD(void, on_trans_updated, (const char* stdCode, WTSTransData* newTrans), (override));
    
    // 添加测试辅助变量
    std::atomic<int> tickCount{0};
    std::atomic<int> barCount{0};
    std::atomic<int> scheduleCount{0};
};

/*!
 * \class MockBaseDataManager
 * \brief 模拟基础数据管理器
 */
class MockBaseDataManager : public WTSBaseDataMgr {
public:
    MockBaseDataManager() : WTSBaseDataMgr() {}
    
    MOCK_METHOD(WTSSessionInfo*, getSession, (const char* sid), (override));
    MOCK_METHOD(WTSCommodityInfo*, getCommodity, (const char* exchg, const char* product), (override));
    MOCK_METHOD(WTSContractInfo*, getContract, (const char* code, const char* exchg), (override));
};

/*!
 * \class MockHotManager
 * \brief 模拟主力合约管理器
 */
class MockHotManager : public WTSHotMgr {
public:
    MockHotManager() : WTSHotMgr() {}
    
    MOCK_METHOD(const char*, getPrevRawCode, (const char* exchg, const char* pid, uint32_t dt), (override));
    MOCK_METHOD(const char*, getRawCode, (const char* exchg, const char* pid, uint32_t dt), (override));
    MOCK_METHOD(bool, isHot, (const char* exchg, const char* rawCode, uint32_t dt), (override));
    MOCK_METHOD(bool, splitHotSecions, (const char* exchg, const char* pid, uint32_t sDt, uint32_t eDt, HotSections& sections), (override));
};

/*!
 * \class HisDataReplayerTest
 * \brief HisDataReplayer测试套件
 */
class HisDataReplayerTest : public ::testing::Test {
protected:
    void SetUp() override {
        replayer = std::make_unique<HisDataReplayer>();
        dataSink = std::make_shared<NiceMock<MockDataSink>>();
        bdMgr = std::make_shared<NiceMock<MockBaseDataManager>>();
        hotMgr = std::make_shared<NiceMock<MockHotManager>>();
        
        // 创建配置
        cfg = WTSVariant::createObject();
        cfg->append("mode", "csv", false);
        cfg->append("path", "./testdata", false);
        cfg->append("stime", "201901010930", false);
        cfg->append("etime", "201912311500", false);
        
        // 创建模拟的会话信息
        mockSession = WTSSessionInfo::create("TRADING", "交易时段", 0);
        mockSession->addTradingSection(93000, 113000);
        mockSession->addTradingSection(133000, 150000);
        
        // 设置基础数据管理器的默认行为
        ON_CALL(*bdMgr, getSession(_))
            .WillByDefault(Return(mockSession));
    }
    
    void TearDown() override {
        if (cfg) cfg->release();
        if (mockSession) mockSession->release();
    }
    
    std::unique_ptr<HisDataReplayer> replayer;
    std::shared_ptr<MockDataSink> dataSink;
    std::shared_ptr<MockBaseDataManager> bdMgr;
    std::shared_ptr<MockHotManager> hotMgr;
    WTSVariant* cfg;
    WTSSessionInfo* mockSession = nullptr;
};

/*!
 * \brief 测试回放器初始化
 * 
 * \details 验证回放器的初始化流程和配置加载
 */
TEST_F(HisDataReplayerTest, TestReplayerInitialization) {
    // 初始化回放器
    EXPECT_TRUE(replayer->init(cfg, nullptr, bdMgr.get(), hotMgr.get()));
    
    // 注册数据接收器
    replayer->register_sink(dataSink.get(), "test_sink");
    
    // 期望初始化事件被触发
    EXPECT_CALL(*dataSink, handle_init()).Times(1);
    
    std::cout << "回放器初始化测试通过" << std::endl;
}

/*!
 * \brief 测试Tick数据回放
 * 
 * \details 验证Tick数据的加载和按时间顺序回放
 */
TEST_F(HisDataReplayerTest, TestTickDataReplay) {
    replayer->init(cfg, nullptr, bdMgr.get(), hotMgr.get());
    replayer->register_sink(dataSink.get(), "test_sink");
    
    // 订阅Tick数据
    replayer->sub_tick(1, "SHFE.rb2501");
    
    // 设置Tick计数器
    ON_CALL(*dataSink, handle_tick(_, _))
        .WillByDefault(Invoke([this](const char* code, WTSTickData* tick) {
            dataSink->tickCount++;
            EXPECT_STREQ(code, "SHFE.rb2501");
            EXPECT_GT(tick->price(), 0);
        }));
    
    // 期望收到Tick数据
    EXPECT_CALL(*dataSink, handle_tick(_, _)).Times(AtLeast(0));
    
    std::cout << "Tick数据回放测试通过" << std::endl;
}

/*!
 * \brief 测试K线数据回放
 * 
 * \details 验证K线数据的加载和闭合事件触发
 */
TEST_F(HisDataReplayerTest, TestBarDataReplay) {
    replayer->init(cfg, nullptr, bdMgr.get(), hotMgr.get());
    replayer->register_sink(dataSink.get(), "test_sink");
    
    // 订阅K线数据
    replayer->sub_bars(1, "SHFE.rb2501", "m1");
    
    // 设置K线计数器
    ON_CALL(*dataSink, handle_bar_close(_, _, _, _))
        .WillByDefault(Invoke([this](const char* code, const char* period, uint32_t times, WTSBarStruct* bar) {
            dataSink->barCount++;
            EXPECT_STREQ(code, "SHFE.rb2501");
            EXPECT_STREQ(period, "m1");
            EXPECT_GT(bar->close, 0);
        }));
    
    // 期望收到K线闭合事件
    EXPECT_CALL(*dataSink, handle_bar_close(_, _, _, _)).Times(AtLeast(0));
    
    std::cout << "K线数据回放测试通过" << std::endl;
}

/*!
 * \brief 测试Level2数据回放
 * 
 * \details 验证委托队列、委托明细、成交明细的回放
 */
TEST_F(HisDataReplayerTest, TestLevel2DataReplay) {
    replayer->init(cfg, nullptr, bdMgr.get(), hotMgr.get());
    replayer->register_sink(dataSink.get(), "test_sink");
    
    // 订阅Level2数据
    replayer->sub_order_queue(1, "SHSE.600036");
    replayer->sub_order_detail(1, "SHSE.600036");
    replayer->sub_transaction(1, "SHSE.600036");
    
    // 期望收到Level2数据
    EXPECT_CALL(*dataSink, handle_order_queue(_, _)).Times(AtLeast(0));
    EXPECT_CALL(*dataSink, handle_order_detail(_, _)).Times(AtLeast(0));
    EXPECT_CALL(*dataSink, handle_transaction(_, _)).Times(AtLeast(0));
    
    std::cout << "Level2数据回放测试通过" << std::endl;
}

/*!
 * \brief 测试时间控制
 * 
 * \details 验证回放器的时间控制和调度功能
 */
TEST_F(HisDataReplayerTest, TestTimeControl) {
    replayer->init(cfg, nullptr, bdMgr.get(), hotMgr.get());
    replayer->register_sink(dataSink.get(), "test_sink");
    
    // 设置调度计数器
    ON_CALL(*dataSink, handle_schedule(_, _))
        .WillByDefault(Invoke([this](uint32_t date, uint32_t time) {
            dataSink->scheduleCount++;
            EXPECT_GE(date, 20190101);
            EXPECT_LE(date, 20191231);
        }));
    
    // 期望收到调度事件
    EXPECT_CALL(*dataSink, handle_schedule(_, _)).Times(AtLeast(0));
    
    std::cout << "时间控制测试通过" << std::endl;
}

/*!
 * \brief 测试会话管理
 * 
 * \details 验证交易时段的开始和结束事件
 */
TEST_F(HisDataReplayerTest, TestSessionManagement) {
    replayer->init(cfg, nullptr, bdMgr.get(), hotMgr.get());
    replayer->register_sink(dataSink.get(), "test_sink");
    
    // 期望收到会话事件
    EXPECT_CALL(*dataSink, handle_session_begin(_)).Times(AtLeast(0));
    EXPECT_CALL(*dataSink, handle_session_end(_)).Times(AtLeast(0));
    
    std::cout << "会话管理测试通过" << std::endl;
}

/*!
 * \brief 测试复权因子处理
 * 
 * \details 验证回放器对复权因子的加载和应用
 */
TEST_F(HisDataReplayerTest, TestAdjustFactorHandling) {
    replayer->init(cfg, nullptr, bdMgr.get(), hotMgr.get());
    
    // 获取复权因子
    double factor = replayer->get_adj_factor("SHSE.600036", 20190101);
    EXPECT_GE(factor, 0.0); // 复权因子应该非负
    
    // 测试无复权因子的情况
    double noFactor = replayer->get_adj_factor("INVALID.CODE", 20190101);
    EXPECT_EQ(noFactor, 1.0); // 默认应该返回1.0
    
    std::cout << "复权因子处理测试通过" << std::endl;
}

/*!
 * \brief 测试数据切片获取
 * 
 * \details 验证获取历史数据切片的功能
 */
TEST_F(HisDataReplayerTest, TestDataSliceRetrieval) {
    replayer->init(cfg, nullptr, bdMgr.get(), hotMgr.get());
    
    // 获取Tick切片
    auto tickSlice = replayer->get_tick_slice("SHFE.rb2501", 10);
    if (tickSlice) {
        EXPECT_LE(tickSlice->size(), 10);
        tickSlice->release();
    }
    
    // 获取K线切片
    auto klineSlice = replayer->get_kline_slice("SHFE.rb2501", "m1", 60);
    if (klineSlice) {
        EXPECT_LE(klineSlice->size(), 60);
        klineSlice->release();
    }
    
    std::cout << "数据切片获取测试通过" << std::endl;
}

/*!
 * \brief 测试多数据接收器
 * 
 * \details 验证支持多个数据接收器的功能
 */
TEST_F(HisDataReplayerTest, TestMultipleDataSinks) {
    replayer->init(cfg, nullptr, bdMgr.get(), hotMgr.get());
    
    // 创建多个数据接收器
    auto sink2 = std::make_shared<NiceMock<MockDataSink>>();
    auto sink3 = std::make_shared<NiceMock<MockDataSink>>();
    
    // 注册多个接收器
    replayer->register_sink(dataSink.get(), "sink1");
    replayer->register_sink(sink2.get(), "sink2");
    replayer->register_sink(sink3.get(), "sink3");
    
    // 期望所有接收器都收到初始化事件
    EXPECT_CALL(*dataSink, handle_init()).Times(AtLeast(0));
    EXPECT_CALL(*sink2, handle_init()).Times(AtLeast(0));
    EXPECT_CALL(*sink3, handle_init()).Times(AtLeast(0));
    
    std::cout << "多数据接收器测试通过" << std::endl;
}

/*!
 * \brief 测试回放控制
 * 
 * \details 验证回放的启动、暂停、停止等控制功能
 */
TEST_F(HisDataReplayerTest, TestReplayControl) {
    replayer->init(cfg, nullptr, bdMgr.get(), hotMgr.get());
    replayer->register_sink(dataSink.get(), "test_sink");
    
    // 准备回放
    EXPECT_TRUE(replayer->prepare());
    
    // 期望收到回放完成事件
    EXPECT_CALL(*dataSink, handle_replay_done()).Times(AtLeast(0));
    
    // 注意：实际回放需要数据文件，这里只测试接口调用
    
    std::cout << "回放控制测试通过" << std::endl;
}

/*!
 * \brief 测试错误处理
 * 
 * \details 验证回放器的错误处理能力
 */
TEST_F(HisDataReplayerTest, TestErrorHandling) {
    // 测试空配置初始化
    EXPECT_FALSE(replayer->init(nullptr, nullptr, nullptr, nullptr));
    
    // 测试无效配置
    auto invalidCfg = WTSVariant::createObject();
    EXPECT_FALSE(replayer->init(invalidCfg, nullptr, nullptr, nullptr));
    invalidCfg->release();
    
    // 测试未初始化状态下的操作
    EXPECT_FALSE(replayer->prepare());
    EXPECT_FALSE(replayer->run());
    
    // 测试空数据接收器
    replayer->init(cfg, nullptr, bdMgr.get(), hotMgr.get());
    replayer->register_sink(nullptr, "null_sink"); // 不应该崩溃
    
    std::cout << "错误处理测试通过" << std::endl;
}

/*!
 * \brief 测试性能特性
 * 
 * \details 验证回放器的性能表现
 */
TEST_F(HisDataReplayerTest, TestPerformanceCharacteristics) {
    replayer->init(cfg, nullptr, bdMgr.get(), hotMgr.get());
    replayer->register_sink(dataSink.get(), "test_sink");
    
    // 订阅多个品种
    const int NUM_SYMBOLS = 10;
    for (int i = 0; i < NUM_SYMBOLS; ++i) {
        std::string symbol = "SHFE.rb250" + std::to_string(i);
        replayer->sub_tick(i + 1, symbol.c_str());
        replayer->sub_bars(i + 1, symbol.c_str(), "m1");
    }
    
    // 测试配置加载性能
    auto start = std::chrono::high_resolution_clock::now();
    bool prepared = replayer->prepare();
    auto end = std::chrono::high_resolution_clock::now();
    
    auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
    
    // 准备时间应该在合理范围内（假设1秒）
    EXPECT_LT(duration.count(), 1000);
    
    std::cout << "性能特性测试通过:" << std::endl;
    std::cout << "  订阅品种数: " << NUM_SYMBOLS << std::endl;
    std::cout << "  准备耗时: " << duration.count() << " 毫秒" << std::endl;
}